package sqlGo

import (
	crand "crypto/rand"
	"fmt"
	mrand "math/rand"
	"regexp"
	"strconv"
	"strings"
	"time"
)

//String 类型转换
func String(val interface{}) string {
	switch val.(type) {
	case string:
		return val.(string)
	case int:
		return strconv.FormatInt(int64(val.(int)), 10)
	case int8:
		return strconv.FormatInt(int64(val.(int8)), 10)
	case int16:
		return strconv.FormatInt(int64(val.(int16)), 10)
	case int32:
		return strconv.FormatInt(int64(val.(int32)), 10)
	case int64:
		return strconv.FormatInt(int64(val.(int64)), 10)
	case uint:
		return strconv.FormatUint(uint64(val.(uint)), 10)
	case uint8:
		return strconv.FormatUint(uint64(val.(uint8)), 10)
	case uint16:
		return strconv.FormatUint(uint64(val.(uint16)), 10)
	case uint32:
		return strconv.FormatUint(uint64(val.(uint32)), 10)
	case uint64:
		return strconv.FormatUint(uint64(val.(uint64)), 10)
	case bool:
		return strconv.FormatBool(val.(bool))
	case float32:
		return strconv.FormatFloat(val.(float64), 'f', -1, 32)
	case float64:
		return strconv.FormatFloat(val.(float64), 'f', -1, 64)
	default:
		return ""
	}
}

//FormatInt 整数转字符串
func FormatInt(val interface{}) string {
	switch val.(type) {
	case int:
		return strconv.FormatInt(int64(val.(int)), 10)
	case int8:
		return strconv.FormatInt(int64(val.(int8)), 10)
	case int16:
		return strconv.FormatInt(int64(val.(int16)), 10)
	case int32:
		return strconv.FormatInt(int64(val.(int32)), 10)
	case int64:
		return strconv.FormatInt(int64(val.(int64)), 10)
	case uint:
		return strconv.FormatUint(uint64(val.(uint)), 10)
	case uint8:
		return strconv.FormatUint(uint64(val.(uint8)), 10)
	case uint16:
		return strconv.FormatUint(uint64(val.(uint16)), 10)
	case uint32:
		return strconv.FormatUint(uint64(val.(uint32)), 10)
	case uint64:
		return strconv.FormatUint(uint64(val.(uint64)), 10)
	case float32:
		return strconv.FormatFloat(float64(val.(float32)), 'f', 0, 32)
	case float64:
		return strconv.FormatFloat(val.(float64), 'f', 0, 64)
	default:
		return ""
	}
}

//ToInt Interface转数字
func ToInt(v interface{}) int64 {
	switch v.(type) {
	case int:
		return int64(v.(int))
	case int8:
		return int64(v.(int8))
	case int16:
		return int64(v.(int16))
	case int32:
		return int64(v.(int32))
	case int64:
		return int64(v.(int64))
	case uint:
		return int64(v.(uint))
	case uint8:
		return int64(v.(uint8))
	case uint16:
		return int64(v.(uint16))
	case uint32:
		return int64(v.(uint32))
	case uint64:
		return int64(v.(uint64))
	case bool:
		tempB := v.(bool)
		if tempB {
			return 1
		}
		return 0
	case float32:
		tempV, err := strconv.Atoi(strconv.FormatFloat(float64(v.(float32)), 'f', 0, 32))
		if err != nil {
			return 0
		}
		return int64(tempV)

	case float64:
		tempV, err := strconv.Atoi(strconv.FormatFloat(v.(float64), 'f', 0, 64))
		if err != nil {
			return 0
		}
		return int64(tempV)

	case string:
		fv, err := strconv.ParseFloat(v.(string), 64)
		if err != nil {
			return -1
		}
		iStr := strconv.FormatFloat(float64(fv), 'f', 0, 64)
		tempValue, err := strconv.Atoi(iStr)
		if err != nil {
			return 0
		}
		return int64(tempValue)

	default:
		return -1
	}
}

/***********主键**********/
//
var seeded = true

var uuidRegex = regexp.MustCompile(`^\{?([a-fA-F0-9]{8})-?([a-fA-F0-9]{4})-?([a-fA-F0-9]{4})-?([a-fA-F0-9]{4})-?([a-fA-F0-9]{12})\}?$`)

type uuid [16]byte

// Hex returns a hex string representation of the UUID in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format.
func (p uuid) hex() string {
	x := [16]byte(p)
	return fmt.Sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
		x[0], x[1], x[2], x[3], x[4],
		x[5], x[6],
		x[7], x[8],
		x[9], x[10], x[11], x[12], x[13], x[14], x[15])

}

// Rand generates a new version 4 UUID.
func rand() uuid {
	var x [16]byte
	randBytes(x[:])
	x[6] = (x[6] & 0x0F) | 0x40
	x[8] = (x[8] & 0x3F) | 0x80
	return x
}

// randBytes uses crypto random to get random numbers. If fails then it uses math random.
func randBytes(x []byte) {

	length := len(x)
	n, err := crand.Read(x)

	if n != length || err != nil {
		if !seeded {
			mrand.Seed(time.Now().UnixNano())
		}

		for length > 0 {
			length--
			x[length] = byte(mrand.Int31n(256))
		}
	}
}

//UUID 返回32位主键
func UUID() string {
	return strings.ToUpper(strings.Replace(rand().hex(), "-", "", -1))
}
